package com.example.his.api.mis.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.example.his.api.common.FaceAuthUtil;
import com.example.his.api.common.MinioUtil;
import com.example.his.api.common.PageUtils;
import com.example.his.api.db.dao.*;
import com.example.his.api.exception.HisException;
import com.example.his.api.mis.service.AppointmentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service("MisAppointmentService")
public class AppointmentServiceImpl implements AppointmentService {
  
  @Resource
  private AppointmentDao appointmentDao;
  
  @Resource
  private GoodsSnapshotDao goodsSnapshotDao;
  
  @Resource
  private CheckupResultDao checkupResultDao;
  
  @Resource
  private FaceAuthUtil faceAuthUtil;
  
  @Resource
  private MinioUtil minioUtil;
  
  @Resource
  private OrderDao orderDao;
  
  @Resource
  private CheckupReportDao checkupReportDao;
  
  
  @Override
  public ArrayList <HashMap> searchByOrderId(int orderId) {
    ArrayList <HashMap> list = appointmentDao.searchByOrderId(orderId);
    return list;
  }
  
  @Override
  public PageUtils searchByPage(Map param) {
    ArrayList list = new ArrayList();
    long count = appointmentDao.searchMisAppointmentCount(param);
    if(count > 0) {
      list = appointmentDao.searchMisAppointmentByPage(param);
    }
    
    int page = (int)param.get("page");
    int length = (int)param.get("length");
    PageUtils pageUtils = new PageUtils(list, count, page, length);
    
    return pageUtils;
  }
  
  @Override
  @Transactional
  public int deleteByIds(Integer[] ids) {
    int i = appointmentDao.deleteByIds(ids);
    return i;
  }
  
  @Override
  public int hasAppointInToday(Map param) {
    HashMap map = appointmentDao.hasAppointInToday(param);
    if(map == null) {
      return 0;     // 没有预约
    } else {
      return MapUtil.getInt(map, "status");
      // 1.有预约，未签到，2：已签到,3已结束，4已关闭
    }
  }
  
  @Override
  @Transactional
  public boolean isCheckin(Map param) {
    String pid = MapUtil.getStr(param, "pid");
    String name = MapUtil.getStr(param, "name");
    String sex = IdcardUtil.getGenderByIdCard(pid) == 1 ? "男" : "女";
    String photo_1 = MapUtil.getStr(param, "photo_1");
    String photo_2 = MapUtil.getStr(param, "photo_2");
    
    //    执行人脸识别
    boolean result = faceAuthUtil.verifyFaceModel(name, pid, sex, photo_1, photo_2);
    if(result) {
      //      将用户照片保存到minio，保留体检人敲到证据
      String filename = pid + ".jpg";
      String path = "checkin/" + "_" + new DateTime().toDateStr() + filename;
      minioUtil.uploadImage(path, photo_2);
      //      更新体检预约状态为已签到
      int rows = appointmentDao.checkin(param);
      if(rows != 1) {
        throw new HisException("更新体检预约状态失败");
      }
      //      查询体检流水号和订单快照id
      HashMap map = appointmentDao.searchUuidAndSnapshotId(param);
      String uuid = MapUtil.getStr(map, "uuid");
      String snapshotId = MapUtil.getStr(map, "snapshotId");
      List <Map> checkup = goodsSnapshotDao.searchCheckup(snapshotId, sex);
      // 添加体检结果记录
      boolean bool = checkupResultDao.insert(uuid, checkup);
      if(! bool) {
        throw new HisException("添加体检结果记录失败");
      }
    }
    
    return result;
  }
  
  //  体检项
  @Override
  public HashMap searchGuidanceInfo(int id) {
    HashMap map = appointmentDao.searchSummaryById(id);
    String snapshotId = MapUtil.getStr(map, "snapshotId");
    String sex = MapUtil.getStr(map, "sex");
    //    生成二维码图片base64字符串
    String uuid = MapUtil.getStr(map, "uuid");
    QrConfig qrConfig = new QrConfig();
    qrConfig.setWidth(100);
    qrConfig.setHeight(100);
    qrConfig.setMargin(0);
    String qrCodeBase64 = QrCodeUtil.generateAsBase64(uuid, qrConfig, "jpg");
    map.put("qrCodeBase64", qrCodeBase64);
    
    List <Map> list = goodsSnapshotDao.searchCheckup(snapshotId, sex);
    LinkedHashSet <Map> set = new LinkedHashSet();
    list.forEach(item -> {
      HashMap <Object, Object> temp = new HashMap <>() {{
        put("place", MapUtil.getStr(item, "place"));
        put("name", MapUtil.getStr(item, "name"));
      }};
      set.add(temp);
    });
    map.put("checkup", set);
    
    return map;
  }
  
  @Override
  @Transactional
  public boolean updateStatusByUuid(Map param) {
    int rows = appointmentDao.updateStatusByUuid(param);
    if(rows != 1) {
      return false;
    }
    Integer status = MapUtil.getInt(param, "status");
    if(status == 3) {
      //      检查对应的订单是否所有的体检预约都已经结束
      String uuid = MapUtil.getStr(param, "uuid");
      HashMap map = orderDao.searchOrderIsFinished(uuid);
      int orderId = MapUtil.getInt(map, "id");
      Integer n1 = MapUtil.getInt(map, "n1");
      Integer n2 = MapUtil.getInt(map, "n2");
      if(n1 == n2) {
        //        订单已经全部预约完成了
        rows = orderDao.updateStatus(new HashMap() {{
          put("status", 6);
          put("id", orderId);
        }});
        if(rows != 1) {
          return false;
        }
      }
      //      查询体检结果id
      String resultId = checkupResultDao.searchIdByUuid(uuid);
      param.put("resultId", resultId);
      rows = checkupReportDao.insert(param);
      if(rows != 1) {
        return false;
      }
    }
    
    return true;
  }
  
  @Override
  public HashMap searchByUuid(String uuid) {
    HashMap map = appointmentDao.searchByUuid(uuid);
    if(map == null) {
      throw new HisException("不存在体检预约记录");
    }
    Integer status = MapUtil.getInt(map, "status");
    if(status == 1) {
      throw new HisException("该体检预约未签到");
    } else if(status == 3) {
      throw new HisException("该体检预约已结束");
    }
    return map;
  }
  
  @Override
  public HashMap searchDataForWaybill(String uuid) {
    HashMap map = appointmentDao.searchDataForWaybill(uuid);
    return map;
  }
}
